package com.lw;

import javax.servlet.Servlet;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * tomcat启动的主线程
 */
public class Tomcat {
    private Map<String,Context> contextMap = new HashMap<>();

    public void start() {
        //socket连接tcp
        try (ServerSocket serverSocket = new ServerSocket(8080)) {
            ExecutorService executorService = Executors.newFixedThreadPool(3);

            while (true) {//死循环是防止处理一次请求后就服务停止
                Socket socket = serverSocket.accept();
                executorService.execute(new SocketProcessor(socket,this));
            }


//            InputStream inputStream = socket.getInputStream();
//            socket.getOutputStream().write(0);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        Tomcat tomcat = new Tomcat();

        //部署应用
        tomcat.deployApps();

        tomcat.start();
    }

    /**
     * 部署应用
     * 就是找webapps下的应用
     * 此处myserver就是一个模拟的应用
     */
    private void deployApps() {
        File webapps = new File(System.getProperty("user.dir"), "webapps");
        for (String app : webapps.list()) {
            deployApp(webapps, app);
        }
    }

    /**
     * 找对应的servlet，将url和servlet形成 key:value
     */
    private void deployApp(File webapps, String appName) {
        File appDirectory = new File(webapps, appName);
        File classesDirectory = new File(appDirectory, "classes");

        Context context = new Context(appName);

        //自定义的类加载器
        WebAppClassLoader classLoader = null;

        try {
            classLoader = new WebAppClassLoader(new URL[]{classesDirectory.toURI().toURL()});
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }

        List<File> files = getAllFilePath(classesDirectory);
        for (File file : files) {
            //找class文件，用反射判断是否是servlet
            String name = file.getPath();
            //name = E:\workspace\idea_workspace\MyTomcat\webapps\myserver\classes\com\server\MyServlet.class
            if (name.lastIndexOf(".class") > 0) {
                // E:\workspace\idea_workspace\MyTomcat\webapps\myserver\classes
                name = name.replace(classesDirectory.getPath() + "\\", "");
                name = name.replace(".class", "");

                //将com\server\MyServlet 变为 com.server.MyServlet 包的格式
                name = name.replace("\\", ".");
//                System.out.println(name);
                try {
                    /*
                     Thread.currentThread().getContextClassLoader().loadClass(name)
                     这是加载不到类的，因为webapps目录不属于MyTomcat下的classes，不能使用此类加载器
                     所以使用自定义的类加载器——WebAppClassLoader
                     */
                    Class<?> servletClass = classLoader.loadClass(name);

                    //alt+enter快捷键 选的flip可以快速转换不等式
                    if (HttpServlet.class.isAssignableFrom(servletClass)) {
                        if(servletClass.isAnnotationPresent(WebServlet.class)){
                            WebServlet annotation = servletClass.getAnnotation(WebServlet.class);
                            String[] urlPatterns = annotation.urlPatterns();

                            for (String urlPattern : urlPatterns) {
                                //添加url和servlet的映射
                                context.addUrlPatternMap(urlPattern, (Servlet) servletClass.newInstance());
                            }
                        }
                    }
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                } catch (InstantiationException e) {
                    throw new RuntimeException(e);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }


        }

        contextMap.put(appName,context);

    }

    public Map<String, Context> getContextMap() {
        return contextMap;
    }

    /**
     * 递归遍历文件
     *
     * @param srcFile
     * @return
     */
    public List<File> getAllFilePath(File srcFile) {
        List<File> result = new ArrayList<>();
        File[] files = srcFile.listFiles();

        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    result.addAll(getAllFilePath(file));
                } else {
                    result.add(file);
                }
            }
        }
        return result;
    }

}
